<template>
  <div>
    <Category :disabled="isAddShow" />

    <el-card
      shadow="always"
      :body-style="{ padding: '20px' }"
      style="margin-top: 30px"
      v-show="!isAddShow"
    >
      <template #header>
        <el-button
          type="primary"
          size="default"
          icon="ele-Plus"
          @click="addAttr"
          :disabled="!category3Id"
          >添加属性</el-button
        >
      </template>
      <!-- card body -->
      <el-table :data="attrList" border stripe>
        <el-table-column type="index" width="80" label="序号" />
        <el-table-column label="属性名称" prop="attrName"></el-table-column>
        <el-table-column
          label="属性值名称列表"
          width="500"
          prop="attrValueList"
        >
          <template v-slot="{ row }">
            <el-tag
              style="margin-right: 5px"
              type="danger"
              size="default"
              effect="dark"
              v-for="item in row.attrValueList"
              :key="item.id"
              >{{ item.valueName }}</el-tag
            >
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template v-slot="{ row }">
            <el-button
              type="warning"
              size="small"
              icon="ele-Edit"
              @click="updateAttr(row)"
            ></el-button>
            <el-popconfirm
              title="你确定要删除我吗?"
              @confirm="confirmDelete(row.id)"
            >
              <template #reference>
                <el-button
                  type="danger"
                  size="small"
                  icon="ele-Delete"
                ></el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <el-card
      shadow="always"
      :body-style="{ padding: '20px' }"
      style="margin-top: 30px"
      v-show="isAddShow"
    >
      <el-form label-width="80px" :inline="true">
        <el-form-item label="属性名">
          <el-input v-model="newAttr.attrName" />
        </el-form-item>
      </el-form>
      <div>
        <el-button
          type="primary"
          size="default"
          @click="addAttrValue"
          :disabled="!newAttr.attrName"
          >添加属性值</el-button
        >
        <el-button type="default" size="default" @click="isAddShow = false"
          >取消</el-button
        >
      </div>
      <el-table
        :data="newAttr.attrValueList"
        border
        stripe
        style="margin: 20px 0"
      >
        <el-table-column type="index" width="80" label="序号" />
        <el-table-column label="属性值名称">
          <template v-slot="{ row, $index }">
            <el-input
              v-if="row.isEdit"
              v-model="row.valueName"
              size="small"
              clearable
              @blur="toLook(row, $index)"
              ref="editEle"
            ></el-input>
            <span v-else @click="toEdit(row)">{{ row.valueName }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template v-slot="{ $index }">
            <el-button
              type="danger"
              size="small"
              icon="ele-Delete"
              @click="deleteAttrValue($index)"
            ></el-button>
          </template>
        </el-table-column>
      </el-table>
      <div>
        <el-button
          type="primary"
          size="default"
          @click="save"
          :disabled="!newAttr.attrName || newAttr.attrValueList.length === 0"
          >保存</el-button
        >
        <el-button type="default" size="default" @click="isAddShow = false"
          >取消</el-button
        >
      </div>
    </el-card>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
// import { nextTick } from "process";

export default defineComponent({
  name: "Attr",
});
</script>

<script setup lang="ts">
import { watch, ref, nextTick } from "vue";
import { storeToRefs } from "pinia";
import {
  reqAttrInfoList,
  type attrListType,
  type attrItemType,
  type attrValueItemType,
  reqAddOrUpdateAttrList,
  reqDeleteAttr,
} from "@/api/attr";
import { ElMessage } from "element-plus";
import useCategoryStore from "@/stores/category";
import { cloneDeep } from "lodash";
const categoryStore = useCategoryStore();

//拿到三级分类的值
const { category1Id, category2Id, category3Id } = storeToRefs(categoryStore);
//初始化一个属性列表的数据
const attrList = ref<attrListType>([]);

//封装请求属性列表的函数
const getAttrList = async () => {
  //一旦3Id改变,则重新发送请求
  try {
    const result = await reqAttrInfoList(
      category1Id.value as number,
      category2Id.value as number,
      category3Id.value as number
    );

    //对初始值进行赋值
    attrList.value = result;
  } catch (e: any) {
    ElMessage.error(e.message);
  }
};
//等到三级分类的第三级的id改变以后,初始化发送属性列表请求
watch(category3Id, async (newVal) => {
  //因为初始化一级分类的时候,三级分类也会发生改变,变为null,但是此时不需要重新发送请求
  if (!newVal) {
    attrList.value = [];
    return;
  }

  //重新请求
  getAttrList();
});

//声明一个值 控制新增属性和属性列表组件的切换
const isAddShow = ref(false);

//声明一个变量,用来收集新增或者修改的属性的数据
const newAttr = ref<attrItemType>({
  attrName: "", //当前平台属性的名字
  categoryId: category3Id.value as number, //固定的当前的category3Id的值
  categoryLevel: 3, //固定是3
  attrValueList: [], //当前属性的属性值列表
});

const editEle = ref<HTMLInputElement>();

//当点击添加属性值的时候,在newAttr的attrValueList中添加一个数据
const addAttrValue = () => {
  const newAttrValue: attrValueItemType = {
    valueName: "",
    attrId: newAttr.value.id, //当前所在属性的id(新增的时候,属性没有id,没有关系,将来添加到服务端就有了)
    isEdit: true, //新增一个属性,代表当前是编辑模式还是查看模式
  };

  //把新创建的attrValue的值插入到attr的attrValueList中
  newAttr.value.attrValueList.push(newAttrValue);

  nextTick(() => {
    editEle.value?.focus();
  });
};
// 当点击修改某个属性的时候 回调函数
const updateAttr = (row: attrItemType) => {
  isAddShow.value = true;
  newAttr.value = cloneDeep(row);
  // 回填数据之后，我们给每一个属性值对象添加一个isEdit属性，代表当前属性值是编辑模式还是查看模式
  newAttr.value.attrValueList.forEach((item) => {
    item.isEdit = false;
  });
};

// 当点击的是新增属性的时候
const addAttr = () => {
  isAddShow.value = true;
  // 恢复newAttr的值为空
  newAttr.value = {
    attrName: "", //当前平台属性的名字
    categoryId: category3Id.value as number, //固定的当前的category3Id的值
    categoryLevel: 3, //固定是3
    attrValueList: [], //当前属性的属性值列表
  };
};

// 查看模式切换编辑模式事件回调函数
const toEdit = (row: attrValueItemType) => {
  row.isEdit = true;

  // 当数据改变以后，我们需要立即操作最新的DOM，请使用nextTick，等本轮DOM更新结束后才执行回调
  nextTick(() => {
    editEle.value?.focus();
  });
};

// 编辑器模式切换到查看模式
const toLook = (row: attrValueItemType, index: number) => {
  // 判断如果当前row的值为空,则直接把这个row数据从attrVlaueList中删除
  if (row.valueName === "") {
    newAttr.value.attrValueList.splice(index, 1);
  }

  // 查看所有的属性值列表中是否有和当前属性值对象的值相等的
  const isRepeat = newAttr.value.attrValueList.some((item) => {
    // 遍历比较的时候,要避开自己和自己相比
    if (item !== row) {
      return item.valueName === row.valueName;
    }
  });

  // 如果有其他和自己相等的，则还是把当前的数据删除掉
  if (isRepeat) {
    newAttr.value.attrValueList.splice(index, 1);
  }
  row.isEdit = false;
};

//删除某个属性值
const deleteAttrValue = (index: number) => {
  newAttr.value.attrValueList.splice(index, 1);
};

//提交更新或者新增
const save = async () => {
  //整理提交的数据,去掉内部的isEdit属性
  newAttr.value.attrValueList.forEach((item) => {
    delete item.isEdit;
  });

  //校验属性名 和 属性列表都不能为空
  if (!newAttr.value.attrName || newAttr.value.attrValueList.length === 0) {
    return ElMessage.error("属性名或者属性值列表不能为空");
  }

  //发送请求
  try {
    await reqAddOrUpdateAttrList(newAttr.value);
    ElMessage.success("新增或修改成功");

    //切换到属性列表
    isAddShow.value = false;

    //重新请求
    getAttrList();
  } catch (e: any) {
    ElMessage.error(e.message);
  }
};
//删除某个属性的回调函数
const confirmDelete = async (id: number) => {
  try {
    await reqDeleteAttr(id);
    ElMessage.success("删除成功");
    //重新请求
    getAttrList();
  } catch (e: any) {
    ElMessage.error(e.message);
  }
};
</script>

<style scoped></style>
